import createElement from "./createElement.js";
import patchVnode from "./patchVnode.js";

function checkSameVnode(a,b){
    return a.sel === b.sel && a.key ===b.key;
}
export default function updateChildren(parentElm, oldCh , newCh){
    //旧前
    let oldStartIdx = 0;
    //新前
    let newStartIdx = 0;
    //旧后
    let oldEndIdx = oldCh.length-1;
    //新后
    let newEndIdx = newCh.length-1;

    //旧前节点
    let oldStartVnode = oldCh[0];
    //新前节点
    let newStartVnode= newCh[0];
    //旧后节点
    let oldEndVnode = oldCh[oldEndIdx];
    //新后节点
    let newEndVnode  = newCh[newEndIdx];

    let keyMap=null;

    while(oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx){
        //略过undefined
        if(oldStartVnode === null || oldCh[oldStartIdx]=== undefined){
            oldStartVnode = oldCh[++oldStartIdx];
        }
        if(oldEndVnode === null || oldCh[oldEndIdx]=== undefined){
            oldEndVnode = oldCh[--oldEndIdx];
        }
        if(newStartVnode === null || newCh[newStartIdx]=== undefined){
            newStartVnode = newch[++newStartIdx];
        }
        if(newEndVnode === null || newCh[newEndIdx]=== undefined){
            newEndVnode = newch[--newEndIdx];
        }
        if(checkSameVnode(oldStartVnode,newStartVnode)){
            //旧前 新前
            patchVnode(oldStartVnode,newStartVnode);
            oldStartVnode = oldCh[++oldStartIdx]
            newStartVnode = newCh[++newStartIdx]
        }else if(checkSameVnode(oldEndVnode,newEndVnode)){
            //旧后 新后
            patchVnode(oldEndVnode,newEndVnode);
            oldEndVnode = oldCh[--oldEndIdx]
            newEndVnode = newCh[--newEndIdx]
        }else if(checkSameVnode(oldStartVnode,newEndVnode)){
            //新后 旧前
            patchVnode(oldStartVnode,newEndVnode);
            //移动新前指向的这个节点到老节点的旧后的后面
            //如何移动节点：只要插入一个已经在dom树上的节点，它就会被移动 
            parentElm.insertBefore(oldStartVnode.elm,oldEndVnode.elm.nextSibiling)
            oldStartVnode = oldCh[++oldStartIdx]
            newEndVnode = newCh[--newEndIdx]
        }else if(checkSameVnode(oldEndVnode,newStartVnode)){
            //新前 旧后
            patchVnode(oldEndVnode,newStartVnode);
            //移动新前指向的这个节点到老节点的旧前的前面
            parentElm.insertBefore(oldEndVnode.elm,oldStartVnode.elm)
            oldEndVnode = oldCh[--oldEndIdx]
            newStartVnode = newCh[++newStartIdx]
        }else{
            //四种命中都未命中
            //制作keyMap缓存
            if(!keyMap){
                keyMap = {};
                for (let i = oldStartIdx; i <= oldEndIdx; i++) {
                    const key = oldCh[i].key;
                    if(key !== undefined){
                        keyMap[key] = i;
                    }
                }
            }
            const idxInold = keyMap[newStartVnode.key];
            if(idxInold === undefined){
                //全新的项
                //被加入的项不是真正的DOM，放到旧前的前面
                parentElm.insertBefore(createElement(newStartVnode),oldStartVnode.elm)
            }else{
                //移动
                const elmToMove = oldCh[idxInold];
                patchVnode(elmToMove,newStartVnode);
                //把这项标记成undefined，表示已处理完
                oldCh[idxInold] = undefined;
                parentElm.insertBefore(elmToMove.elm,oldStartVnode.elm);
            }
            newStartVnode = newch[++newStartIdx]
        }
    }

    if(newStartIdx<=newEndIdx){
        for (let i = newStartIdx; i <= newEndIdx; i++) {
            //剩余节点插入到 旧前 前
            parentElm.insertBefore(createElement(newCh[i]),oldCh[oldStartIdx].elm);
        }
    }else if(oldStartIdx<=oldEndIdx){
        for(let i=oldStartIdx;i<=oldEndIdx;i++){
            if(oldCh[i]){
                parentElm.removeChild(oldCh[i].elm)
            }
        }
    }
}